package com.yjy.xml;

import com.yjy.xml.v1.CbhbRspTransaction;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.io.StringWriter;

public class JaxbXmlUtil {

    private static final String xmlns_tag = " xsi:type=\"xs:string\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";
    private static final String xsi_nil_tag = " xsi:nil=\"true\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"";

    /**
     * xml转换成bean
     *
     * @param xml    xml字符串
     * @param classT 待转Bean类
     * @return
     * @throws JAXBException
     */
    public static <T> T xmlToBean(String xml, Class<T> classT) throws JAXBException {
        // 获得 JAXBContext 类的新实例。参数为类的地址
        JAXBContext context = JAXBContext.newInstance(classT);
        // 创建一个可以用来将 XML 数据转换为 java 内容树的 Unmarshaller 对象。
        Unmarshaller um = context.createUnmarshaller();
        // 创建一个StringReader将xml报文转成流
        StringReader sr = new StringReader(xml);
        // 调用unmarshal进行转换，并把Object类型强转为调用者的类型
        Object unmarshal = um.unmarshal(sr);
        return (T) unmarshal;
    }

    /**
     * xml转换成bean（含泛型属性）
     *
     * @param xml       xml字符串
     * @param beanClass 待转Bean类
     * @param c         泛型属性类
     * @return
     * @throws JAXBException
     */
    public static <T> T xmlToBean(String xml, Class<T> beanClass, Class c) throws JAXBException {
        // 获得 JAXBContext 类的新实例。参数为类的地址
        JAXBContext context = JAXBContext.newInstance(beanClass, c);
        // 创建一个可以用来将 XML 数据转换为 java 内容树的 Unmarshaller 对象。
        Unmarshaller um = context.createUnmarshaller();
        // 创建一个StringReader将xml报文转成流
        StringReader sr = new StringReader(xml);
        // 调用unmarshal进行转换，并把Object类型强转为调用者的类型
        Object unmarshal = um.unmarshal(sr);
        return (T) unmarshal;
    }

    /**
     * bean转换成xml
     *
     * @param obj 待转化的对象
     * @return
     * @throws JAXBException
     */
    public static String beanToXml(Object obj) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(obj.getClass());
        Marshaller marshaller = context.createMarshaller();
        // 指定是否使用换行和缩排对已编组 XML 数据进行格式化的属性名称。
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter writer = new StringWriter();
        marshaller.marshal(obj, writer);
        String rstXML = writer.toString()
                .replaceAll(" standalone=\"yes\"", "")
                .replaceAll(xsi_nil_tag, "")
                .replaceAll(xmlns_tag, "")
                .replaceAll("&lt;", "<")
                .replaceAll("&gt;", ">");
        return rstXML;
    }

    /**
     * bean转换成xml（含泛型属性）
     *
     * @param obj 待转化的对象
     * @param c   泛型属性
     * @return
     * @throws JAXBException
     */
    public static String beanToXml(Object obj, Class c) throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(obj.getClass(), c);
        Marshaller marshaller = context.createMarshaller();

        // 指定是否使用换行和缩排对已编组 XML 数据进行格式化的属性名称。
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter writer = new StringWriter();
        marshaller.marshal(obj, writer);
        String rstXML = writer.toString()
                .replaceAll(" standalone=\"yes\"", "")
                .replaceAll(xsi_nil_tag, "")
                .replaceAll(xmlns_tag, "")
                .replaceAll("&lt;", "<")
                .replaceAll("&gt;", ">");
        return rstXML;
    }
}
